home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
SciAn
/
src
/
ScianFileSystem.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
41KB
|
1,399 lines
/* ScianFileSystem.c
manages file system window for scian
Jim Lyons
created 4/17/91
4/28/91 version 2 of files window
5/1/91 version 3: made file objects
5/3/91 added format dialog routines
5/29/91 EMP removed lib headers
6/25/91 removed icon definitions
7/22/91 added Read Data Files menu item
8/8/91 guarded all strcpy and strcat calls
9/9/91 added help strings
9/16/91 redesigned file window
9/19/91 added file info window
10/12/91 removed Set File Type stuff
10/28/91 changed interface to File Readers (with EMP)
1/20/92 changed order of file type identification in ReadDir
2/5/92 added DropInContents method to file window corral
4/8/92 made all chdirs temporary, never change dirs on user
4/17/92 changed Open to use Object Function
4/23/92 changed Set Format and Show Info to use Object Functions
5/26/92 EMP fixed OpenParent not to fail at root
5/26/92 EMP made GetFileWindow public
6/13/92 EMP changed to use method declarations, not prototypes
10/15/92 Modified file info window to make two-line directory name
2/3/93 Fixed bug in file info routine
*/
#include "Scian.h"
#ifdef GETPWNAM
#include <pwd.h>
#endif
#include "ScianStyle.h"
#include "ScianTypes.h"
#include "ScianMethods.h"
#include "ScianArrays.h"
#include "ScianFontSystem.h"
#include "ScianWindows.h"
#include "ScianTextBoxes.h"
#include "ScianSliders.h"
#include "ScianButtons.h"
#include "ScianTitleBoxes.h"
#include "ScianObjWindows.h"
#include "ScianObjFunctions.h"
#include "ScianDatabase.h"
#include "ScianSymbols.h"
#include "ScianColors.h"
#include "ScianControls.h"
#include "ScianTimers.h"
#include "ScianLists.h"
#include "ScianIDs.h"
#include "ScianEvents.h"
#include "ScianErrors.h"
#include "ScianDialogs.h"
#include "ScianIcons.h"
#include "ScianFiles.h"
#include "ScianDatasets.h"
#include "ScianScripts.h"
#include "ScianPreferences.h"
#include "ScianFileSystem.h"
/* defs for file window parameters */
#undef TITLEBOXTOP
#define TITLEBOXTOP 14
#define PARENTBTNWID 104
#define PARENTBTNHT 70
#define MINBTNWID 120
#define FILTERBTNWID 218
#define FILESWIDTH (2*MINORBORDER + 2*SMALLGAP + 3*MINBTNWID)
#define FILESHEIGHT 390
/* defs for file format dialog box */
#define RADIOWID 84
#define BOTPART (BOTMARGIN + OKBTNHT + INTERSPACE)
#define STICKYALL (STICKYRIGHT + STICKYLEFT + STICKYBOTTOM + STICKYTOP)
/* defs for file info window */
#define NINFOITEMS 5
#define INFOITEMHT 40
#define INFOITEMWID 110
#define INFONAMEWIDTH 70
#define INFOFIELDWIDTH 200
#define INFOFIELDHEIGHT (NINFOITEMS*INFOITEMHT)
#define INFOWIDTH (3*MINORBORDER + INFONAMEWIDTH + INFOFIELDWIDTH)
#define INFOHEIGHT \
(MINORBORDER + MAJORBORDER + GAP + 2*INFOFONTSIZE + 2*DEFLINESPACE + BARWIDTH + INFOFIELDHEIGHT)
#define INFOFONT "Helvetica-Bold"
#define INFOFONTSIZE 12
/* file selector bit mask */
#define MASK(f) (1<<f)
#define DEFAULTFILTER (MASK(DIRFILE) | MASK(DATAFILE) | MASK(LOGFILE) | MASK(PALFILE))
#define ALLFILES (MASK(NFILETYPES) - 1)
/* EMP static method declarations */
static ObjPtr CancelDialog();
static ObjPtr OKDialog();
static ObjPtr DoParent();
static ObjPtr DropInFileWin();
static ObjPtr OpenParent();
static ObjPtr OpenFile();
static ObjPtr OpenFolder();
static ObjPtr NewFilter();
static ObjPtr ShowFiles();
/* static function prototypes */
#ifdef PROTO
static ObjPtr SetFormat(ObjPtr);
static ObjPtr ShowInfo(ObjPtr);
static char *GetFileInfo(char *, char *);
static void FileFormatDialog(FuncTyp);
static ObjPtr OKFormat(int, ObjPtr);
static void ChangeFileType(ObjPtr, int);
static ObjPtr SelFileList(ObjPtr);
static ObjPtr SelDirList(ObjPtr);
static ObjPtr NewFileWindow(WinInfoPtr, char *);
static Bool ReadDirectory(ObjPtr);
static int FileType(char *);
#else
static ObjPtr SetFormat();
static ObjPtr ShowInfo();
static char *GetFileInfo();
static void FileFormatDialog();
static ObjPtr OKFormat();
static void ChangeFileType();
static ObjPtr SelFileList();
static ObjPtr SelDirList();
static ObjPtr NewFileWindow();
static Bool ReadDirectory();
static int FileType();
#endif
/********************************************************* GLOBALS */
int fileIcon[NFILETYPES] = {ICONFOLDER, ICONBINFILE, ICONOBJFILE, ICONTEXTFILE,
ICONDATAFILE, ICONSCIANDOC, ICONCTABLE, ICONUNKNOWN};
char *fileTypeName[NFILETYPES] = {"Dir", "Bin", "Obj", "Text", "Data",
"SciAn Log", "Palette", "Other"};
char dirSave[MAXPATHLEN+1]; /* save original working directory name */
char replySave[MAXPATHLEN+1]; /* keep dialog reply text for reediting */
ObjPtr aList; /* list for collecting selected files */
/********************************************************** INIT FILE SYSTEM */
void InitFileSystem(void)
{
/* (fileClass is handled by ScianFiles) */
/* ...but set the object function here for double clicking per EMP */
SetVar(fileClass, DOUBLECLICK, NewString(OF_OPEN));
getwd(dirSave); /* save original working directory name */
*replySave = '\0'; /* clear saved path */
}
void KillFileSystem(void)
{
/* (fileClass is handled by ScianFiles) */
}
/******************************************************* OBJ FUNCTION ROUTINES */
#ifdef PROTO
ObjPtr Collect(ObjPtr theFile)
#else
ObjPtr Collect(theFile)
ObjPtr theFile;
#endif
/* used as method for collecting files to Set Format or Show Info */
{
PrefixList(aList, theFile);
return ObjTrue;
}
void SetUpCollect()
/* setup routine for Set Format and Show Info */
{
aList = NewList();
}
void RestoreDir()
/* restores original directory after opening files */
{
chdir(dirSave);
}
/******************************************************* DO NEW FILE WINDOW */
void DoNewFileWindow(void)
/* New File Window menu routine */
{
WinInfoPtr askWindow;
if (logging)
{
Log("Show FilesWindow\n");
InhibitLogging(true);
}
if (*replySave)
{
strncpy(tempStr, replySave, TEMPSTRSIZE);
tempStr[TEMPSTRSIZE] = '\0';
}
else if (PrefExists(PREF_DEFDIR))
{
strncpy(tempStr, GetPrefString(PREF_DEFDIR), TEMPSTRSIZE);
tempStr[TEMPSTRSIZE-1] = '\0';
}
else getwd(tempStr);
askWindow = AskUser((WinInfoPtr) NULLOBJ, "Enter directory name:",
(FuncTyp) NewFileWindow, tempStr);
if (askWindow) SetVar((ObjPtr) askWindow, HELPSTRING, NewString("This dialog window \
allows you to enter the name of the directory for which you want to open a new File Window. \
The default directory name, showing when the window first comes up, may be set in the \
Preferences window."));
if (logging) InhibitLogging(false);
}
static ObjPtr NewFileAgain(WinInfoPtr win, int n)
/* called if error in directory name from New File Window dialog */
{
if (n == 1) DoNewFileWindow();
else *replySave = '\0'; /* clear error string */
return NULLOBJ;
}
#define MAXUSERNAME 20 /*Max # of chars in user name*/
#ifdef PROTO
static ObjPtr NewFileWindow(WinInfoPtr owner, char *replyText)
#else
static ObjPtr NewFileWindow(owner, replyText)
WinInfoPtr owner;
char *replyText;
#endif
/* puts up the New File Window */
{
char *s, t[MAXPATHLEN + 1];
WinInfoPtr alert;
DIR *dirp;
SKIPBLANKS(replyText);
if (*replyText == '~')
{
/*See if next character could be a name*/
if (isdigit(replyText[1]) || isalpha(replyText[1]))
{
/*Must be some nother user*/
#ifdef GETPWNAM
int k;
struct passwd *pwdEntry;
char userName[MAXUSERNAME + 1];
for (k = 1;
k < MAXUSERNAME && (isdigit(replyText[k]) || isalpha(replyText[k]));
++k)
{
userName[k-1] = replyText[k];
}
userName[k-1] = '\0';
pwdEntry = getpwnam(userName);
if (pwdEntry)
{
/*Entry's OK*/
strcpy(t, pwdEntry -> pw_dir);
strcat(t, replyText + k);
}
else
{
/* unknown user */
strcpy(replySave, replyText); /* save text for user reediting */
sprintf(t, "Unknown user, %s.", userName);
alert = AlertUser(UIERRORALERT, owner, t,
NewFileAgain, 2, "Cancel", "Re-enter");
if (alert) SetVar((ObjPtr) alert, HELPSTRING, NewString("You have used the \
'~user' construct in a directory name to find another user's home directory. \
No user with the specified name could be found. Press \
the Re-enter button to correct the entry, or press the Cancel key to cancel the request."));
return ObjTrue;
}
#else
/* save text for user reediting */
strcpy(replySave, replyText);
alert = AlertUser(UIERRORALERT, owner, "Sorry, this version of SciAn does not \
support the '~user' construct in a directory name.", NewFileAgain,
2, "Cancel", "Re-enter");
if (alert) SetVar((ObjPtr) alert, HELPSTRING, NewString("You have used the \
'~user' construct in a directory name to find a user's home directory. This \
version of SciAn has not been compiled to accept this construct. Press \
the Re-enter button to correct the entry, or press the Cancel key to cancel the request."));
return ObjTrue;
#endif
}
else
{
if (s = getenv("HOME")) /* substitute for squiggle */
{
strcpy(t, s);
strcat(t, replyText + 1);
}
}
}
else if (*replyText)
{
strcpy(t, replyText);
}
else
{
t[0] = '/';
t[1] = '\0';
}
if (chdir(t) == 0) /* check if valid directory */
{
getwd(t); /* get expanded name back */
GetFileWindow(t);
*replySave = '\0'; /* clear error string */
chdir(dirSave); /* return to original directory */
return ObjTrue;
}
else /* error */
{
#define PROMPT1 "Could not open directory "
#define PROMPT2 ". Do you want to enter another directory or cancel the request?"
/* save text for user reediting */
strcpy(replySave, replyText);
/* set up prompt in tempStr */
strcpy(tempStr, PROMPT1);
strncat(tempStr, (t ? t : replyText),
TEMPSTRSIZE - strlen(PROMPT1) - strlen(PROMPT2) - 1);
strcat(tempStr, PROMPT2);
alert = AlertUser(UIERRORALERT, owner, tempStr, NewFileAgain,
2, "Cancel", "Re-enter");
if (alert) SetVar((ObjPtr) alert, HELPSTRING, NewString("This dialog window \
came up because the directory entered in the New File Window dialog could not be opened. Press \
the Re-enter button to correct that entry, or press the Cancel key to cancel the request."));
}
return ObjTrue;
}
/******************************************************* SET FORMAT */
void ProcessSetFormat(void)
{
ObjPtr corral;
int fmt, i,n;
if (!selWinInfo || !(corral = GetVar((ObjPtr) selWinInfo, CORRAL))
|| ListCount(aList) == 0) return;
/* now make dialog */
FileFormatDialog(OKFormat);
/*** assuming selWinInfo is now the new dialog ... */
SetVar((ObjPtr) selWinInfo, FILELIST, aList); /* stash file list with dialog */
if (logging) InhibitLogging(false);
return;
}
static ObjPtr OKFormat(int fmt, ObjPtr list)
{
ObjPtr theFile, theRdr, theIcon, keyList, fileReaders;
int i, n = ListCount(list);
/* make a list of all the file readers */
keyList = NewList();
PostfixList(keyList, NewSymbol(CLASSID));
PostfixList(keyList, NewInt(CLASS_FILEREADER));
fileReaders = SearchDatabase(keyList);
/* fmt is the number of the button that was selected in the format group */
if (fmt < 0) return ObjFalse; /* no choice made */
else if (fmt >= ListCount(fileReaders)) /* choice was "none" */
{
for (i=0; i<n; ++i) /* clear FORMAT and READER, leave filetype same */
{
theFile = GetListElem(list, i);
theIcon = GetVar(theFile, REPICON);
SetVar(theFile, READER, NULLOBJ);
SetVar(theIcon, FORMAT, NULLOBJ);
ImInvalid(theIcon); /* cause redraw */
}
}
else
{
for (i=0; i<n; ++i)
{
theFile = GetListElem(list, i);
theRdr = GetListElem(fileReaders, fmt);
SetVar(theFile, READER, theRdr);
ChangeFileType(theFile, DATAFILE);
SetVar(GetVar(theFile, REPICON), FORMAT,
GetVar(theRdr, NAME));
theIcon = GetVar(theFile, REPICON);
ImInvalid(theIcon); /* cause redraw */
}
}
return ObjTrue;
}
/* ChangeFileType routine is somewhat obsolete since we eliminated the Set File Type command.
It is used in one place for Set File Format (in OKFormat above) just to change
a file's type to DATA. I kept the general form in case needed later. JL */
#ifdef PROTO
static void ChangeFileType(ObjPtr theFile, int newType)
#else
static void ChangeFileType(theFile, newType)
ObjPtr theFile;
int newType;
#endif
{
ObjPtr theIcon, theCorral, fileLists;
int oldType;
oldType = GetInt(GetVar(theFile, FILETYPE));
if (oldType == newType) return;
theIcon = GetVar(theFile, REPICON);
theCorral = GetVar(theIcon, PARENT);
fileLists = GetVar(theCorral, FILELIST);
/* take file off old type list, add to new type list */
DeleteFromList(GetListElem(fileLists, oldType), theFile);
PrefixList(GetListElem(fileLists, newType), theFile);
/* change the file type in file and icon */
SetVar(theFile, FILETYPE, NewInt(newType));
SetVar(theIcon, FILETYPE, NewInt(newType));
/* change the icon */
SetVar(theIcon, WHICHICON, NewInt(fileIcon[newType]));
if (newType == DATAFILE) /* just in case a file was changed from data, then back */
{
char *ext, *name;
ObjPtr theRdr;
name = GetString(GetVar(theFile, NAME));
ext = strrchr(name, '.');
if (ext++ && (theRdr = FindExtensionReader(ext) ))
{
/* known data file format */
SetVar(theFile, READER, theRdr);
SetVar(theIcon, FORMAT, GetVar(theRdr, NAME));
}
}
else /* clear format in icon and file */
{
SetVar(theFile, READER, NULLOBJ);
SetVar(theIcon, FORMAT, NULLOBJ);
}
return;
}
/******************************************************************** SHOW INFO */
void ProcessShowInfo(void)
{
WinInfoPtr infoWin;
ObjPtr textbox, thePath, list, theString;
char *path;
int i;
path = GetString(thePath = GetVar(GetListElem(aList, 0), PATH));
if (chdir(path) != 0)
{
ReportError("ProcessShowInfo", "Could not change directory");
return;
}
/* get the info window */
theString = NewString("File Info");
infoWin = GetDialog((WinInfoPtr) NULLOBJ, theString, "File Info",
INFOWIDTH, INFOHEIGHT, INFOWIDTH, INFOHEIGHT, WINUI + WINFIXEDSIZE);
if (textbox = GetVar((ObjPtr) infoWin, REPOBJ)) /* dialog exists */
{
ThingListPtr p;
ObjPtr theFile, field, contents;
char *fileName;
int x, itemWid;
/* pop info window */
PopWindow(infoWin);
SetVar(textbox, VALUE, thePath);
ImInvalid(textbox);
/* put in file info textbox for each file on the list */
field = GetVar((ObjPtr) infoWin, FIELD);
SetVar(field, CONTENTS, contents = NewList());
p = LISTOF(aList);
x = MINORBORDER;
SetupFont(INFOFONT, INFOFONTSIZE); /* so we can check filename length */
while (p)
{
theFile = p -> thing;
fileName = GetString(GetVar(theFile, NAME));
itemWid = StrWidth(fileName);
if (itemWid < INFOITEMWID) itemWid = INFOITEMWID;
textbox = NewTextBox(x, x + itemWid,
-INFOFIELDHEIGHT + MINORBORDER, -MINORBORDER,
PLAIN, "File Info", GetFileInfo(path, fileName));
PrefixList(contents, textbox);
SetVar(textbox, PARENT, field);
SetTextFont(textbox, INFOFONT);
SetTextSize(textbox, INFOFONTSIZE);
SetTextLineSpace(textbox, INFOITEMHT - INFOFONTSIZE);
p = p -> next;
x = x + itemWid + 2*MINORBORDER;
}
ScrollHome(field);
RecalcScroll(field);
}
else /* create info window */
{
ObjPtr field, panel, contents, button;
ThingListPtr p;
ObjPtr theFile;
char *fileName;
int x, itemWid;
contents = GetVar((ObjPtr) infoWin, CONTENTS); /* contents of window */
/* put in help string */
SetVar((ObjPtr) infoWin, HELPSTRING, NewString("This window shows directory \
information for the selected file(s) in the file window. If more than one file was selected, \
you can use the scrollbar at the bottom of the window to view information for each of them."));
/* put in panel */
panel = NewPanel(greyPanelClass, 0, INFOWIDTH, 0, INFOHEIGHT);
PrefixList(contents, panel);
SetVar(panel, PARENT, (ObjPtr) infoWin);
contents = GetVar(panel, CONTENTS); /* contents of panel */
/* put path textbox at top */
textbox = NewTextBox(MINORBORDER, INFOWIDTH - MINORBORDER,
INFOHEIGHT - MAJORBORDER - 2*INFOFONTSIZE - 2*DEFLINESPACE,
INFOHEIGHT - MAJORBORDER, PLAIN, "Pathname", GetString(thePath));
SetVar(textbox, PARENT, panel);
PrefixList(contents, textbox);
SetTextFont(textbox, INFOFONT);
SetTextSize(textbox, INFOFONTSIZE);
SetTextAlign(textbox, RIGHTALIGN);
SetVar((ObjPtr) infoWin, REPOBJ, textbox); /* ref to by this routine */
/* put in "fieldnames" textbox */
textbox = NewTextBox(MINORBORDER, MINORBORDER + INFONAMEWIDTH,
MINORBORDER,
INFOHEIGHT-MAJORBORDER-2*INFOFONTSIZE-2*DEFLINESPACE-GAP-MINORBORDER-1,
PLAIN, "Fieldnames",
"Name\nSize\nOwner\nMode\nModified");
SetVar(textbox, PARENT, panel);
PrefixList(contents, textbox);
SetTextFont(textbox, INFOFONT);
SetTextSize(textbox, INFOFONTSIZE);
SetTextAlign(textbox, RIGHTALIGN);
SetTextLineSpace(textbox, INFOITEMHT-INFOFONTSIZE);
/* put in field for info text boxes */
field = NewControlField(2*MINORBORDER + INFONAMEWIDTH, INFOWIDTH - MINORBORDER,
MINORBORDER, MINORBORDER + INFOFIELDHEIGHT + BARWIDTH,
"Info Field", OBJECTSFROMTOP + BARBOTTOM);
SetVar(field, BACKGROUND, NewInt(UIGRAY75));
SetVar(field, BORDERTYPE, NewInt(1));
SetVar(field, PARENT, panel);
PrefixList(contents, field);
SetVar(field, CONTENTS, contents = NewList());
SetVar((ObjPtr) infoWin, FIELD, field);
/* put in file info textbox for each file on the list */
p = LISTOF(aList);
x = MINORBORDER;
SetupFont(INFOFONT, INFOFONTSIZE); /* so we can check filename length */
while (p)
{
theFile = p -> thing;
fileName = GetString(GetVar(theFile, NAME));
itemWid = StrWidth(fileName);
if (itemWid < INFOITEMWID) itemWid = INFOITEMWID;
textbox = NewTextBox(x, x + itemWid,
-INFOFIELDHEIGHT + MINORBORDER, -MINORBORDER,
PLAIN, "File Info", GetFileInfo(path, fileName));
PrefixList(contents, textbox);
SetVar(textbox, PARENT, field);
SetTextFont(textbox, INFOFONT);
SetTextSize(textbox, INFOFONTSIZE);
SetTextLineSpace(textbox, INFOITEMHT - INFOFONTSIZE);
p = p -> next;
x = x + itemWid + 2*MINORBORDER;
}
RecalcScroll(field);
}
if (logging) InhibitLogging(false);
chdir(dirSave); /* return to original working directory */
return;
}
#ifdef PROTO
static char *GetFileInfo(char *path, char *fileName)
#else
static char *GetFileInfo(path, fileName)
char *path, *fileName;
#endif
{
char *p = tempStr, *s, buf[20];
struct stat stbuf;
struct passwd *pwbuf;
struct tm *tmbuf;
short mode;
s = fileName;
while (*p++ = *s++) ;
*(p - 1) = '\n';
/* get file info */
if (stat(fileName, &stbuf) == -1) /* This happens! (eg, link to a bin, dead link) */
{
strcpy(p, "?\n?\n?\n?");
}
else
{
/* get size in K */
sprintf(buf,"%dK",(stbuf.st_size + 1023)/1024);
s = buf;
while (*p++ = *s++) ;
*(p - 1) = '\n';
/* get owner name */
pwbuf = getpwuid(stbuf.st_uid);
if (pwbuf)
{
s = pwbuf -> pw_name;
}
else
{
s = "(unavailable)";
}
while (*p++ = *s++) ; /* copy name */
*(p - 1) = '\n';
/* get mode bits */
mode = stbuf.st_mode;
*p++ = mode & S_IRUSR ? 'r' : '-';
*p++ = mode & S_IWUSR ? 'w' : '-';
*p++ = mode & S_IXUSR ? 'x' : '-';
*p++ = ' ';
*p++ = mode & S_IRGRP ? 'r' : '-';
*p++ = mode & S_IWGRP ? 'w' : '-';
*p++ = mode & S_IXGRP ? 'x' : '-';
*p++ = ' ';
*p++ = mode & S_IROTH ? 'r' : '-';
*p++ = mode & S_IWOTH ? 'w' : '-';
*p++ = mode & S_IXOTH ? 'x' : '-';
*p++ = '\n';
/* get modified date */
tmbuf = localtime(&stbuf.st_mtime);
sprintf(buf,"%02d/%02d/%02d %02d:%02d\n", tmbuf->tm_mon + 1, tmbuf->tm_mday,
tmbuf->tm_year, tmbuf->tm_hour, tmbuf->tm_min);
s = buf;
while (*p = *s++) ++p;
}
return tempStr;
}
/********************************************************************* FILE FORMAT DIALOG
* Puts up a dialog for selecting data file format.
* The OKRoutine is called with the selected format and list of files:
*
* void OKRoutine(int fmt, ObjPtr list)
*/
#ifdef PROTO
static void FileFormatDialog(FuncTyp OKRoutine)
#else
static void FileFormatDialog(OKRoutine)
FuncTyp OKRoutine;
#endif
{
WinInfoPtr theDialog;
ObjPtr panel, alertPanel, contents, promptBox, radioBtn, cancelBtn, okBtn;
ObjPtr thePrompt, radioGroup, keyList, fileReaders;
int row, col, nRows, nCols, totWid, totHt;
int n, nBtns;
/* make a list of all the file readers */
keyList = NewList();
PostfixList(keyList, NewSymbol(CLASSID));
PostfixList(keyList, NewInt(CLASS_FILEREADER));
fileReaders = SearchDatabase(keyList);
nBtns = ListCount(fileReaders) + 1;
/* first compute sizes from the number of buttons */
/* number of buttons is one more than number of formats to allow for "none" */
if (nBtns < 11) nCols = 2, nRows = (nBtns + 1)/2;
else if (nBtns < 25) nCols = 3, nRows = (nBtns + 2)/3;
else nCols = 4, nRows = (nBtns + 3)/4;
totWid = 2*SIDEMARGIN + nCols*RADIOWID + (nCols - 1)*GAP;
totHt = BOTMARGIN + OKBTNHT + 2*INTERSPACE + nRows*CHECKBOXHEIGHT + (nRows - 1)*GAP
+ PROMPTTEXTSIZE + TOPMARGIN;
/* see if dialog exists */
if (!selWinInfo) return;
thePrompt = NewString("Set file format to:");
theDialog = GetDialog(selWinInfo, thePrompt, "Set Data Format",
totWid, totHt, totWid, totHt,
WINUI + WINFIXEDSIZE + WINCENTERED + WINNOFRAME);
if(!theDialog) return;
if (GetVar((ObjPtr) theDialog, REPOBJ)) /* dialog exists */
{
/* pop the dialog */
PopWindow(theDialog);
}
else /* make the dialog box */
{
ThingListPtr runner;
SetVar((ObjPtr) theDialog, REPOBJ, thePrompt); /* mark dialog */
contents = GetVar((ObjPtr) theDialog, CONTENTS); /* contents of window */
SetVar((ObjPtr) theDialog, HELPSTRING, NewString("This window shows \
the data file formats recognized by this version of SciAn. Click on the proper format \
for the selected files and press the OK button. For more information, see the section \
on data file formats in the SciAn User's manual."));
/* put in panel */
panel = NewPanel(greyPanelClass, 0, totWid, 0, totHt);
PrefixList(contents, panel);
SetVar(panel, PARENT, (ObjPtr) theDialog);
contents = GetVar(panel, CONTENTS); /* contents of panel */
/* put in pretty panel */
alertPanel = NewAlertPanel(0, totWid, 0, totHt, "Fmt Panel");
PrefixList(contents, alertPanel);
SetVar(alertPanel, PARENT, panel);
/* put in prompt */
promptBox = NewTextBox(SIDEMARGIN, totWid - SIDEMARGIN,
totHt - TOPMARGIN - PROMPTTEXTSIZE, totHt - TOPMARGIN,
PLAIN, "Prompt Box", GetString(thePrompt));
PrefixList(contents, promptBox);
SetVar(promptBox, PARENT, panel);
SetVar(promptBox, UIFONT, NewInt(PROMPTTEXTFONT));
SetTextColor(promptBox, PROMPTTEXTCOLOR);
/* put in the bottom buttons */
cancelBtn = NewButton(totWid - SIDEMARGIN - 2*OKBTNWID - GAP,
totWid - SIDEMARGIN - OKBTNWID - GAP,
BOTMARGIN, BOTMARGIN + OKBTNHT, "Cancel");
PrefixList(contents, cancelBtn);
SetVar(cancelBtn, PARENT, panel);
SetMethod(cancelBtn, CHANGEDVALUE, CancelDialog);
SetVar(cancelBtn, HELPSTRING, NewString("Pressing this button \
will cancel this dialog window without changing the format of the selected file(s)."));
okBtn = NewButton(totWid - SIDEMARGIN - OKBTNWID,
totWid - SIDEMARGIN,
BOTMARGIN, BOTMARGIN + OKBTNHT, "OK");
PrefixList(contents, okBtn);
SetVar(okBtn, PARENT, panel);
SetMethod(okBtn, OKMETHOD, OKRoutine); /* for ref by OKDialog */
SetMethod(okBtn, CHANGEDVALUE, OKDialog);
SetVar(okBtn, HELPSTRING, NewString("Pressing this button \
will dismiss this dialog window and set the format of the selected file(s)."));
SetVar(okBtn, REPOBJ, (ObjPtr) theDialog);
/* oh, yeah -- guess we need a few radio buttons */
radioGroup = NewRadioButtonGroup("Data Format");
PrefixList(contents, radioGroup);
SetVar(radioGroup, PARENT, panel);
runner = LISTOF(fileReaders);
for (n=0, row=nRows-1; row>=0 && runner; --row)
{
for (col = 0; col<nCols && runner; ++col)
{
ObjPtr theName;
theName = GetVar(runner -> thing, NAME);
radioBtn = NewRadioButton(
SIDEMARGIN + col*(RADIOWID + GAP),
SIDEMARGIN + (col+1)*RADIOWID + col*GAP,
BOTPART + row*(CHECKBOXHEIGHT + GAP),
BOTPART + (row+1)*CHECKBOXHEIGHT + row*GAP,
theName ? GetString(theName) : "");
AddRadioButton(radioGroup, radioBtn);
runner = runner -> next;
}
}
/* now add "none" button */
row = 0; col = nCols - 1;
radioBtn = NewRadioButton(
SIDEMARGIN + col*(RADIOWID + GAP),
SIDEMARGIN + (col+1)*RADIOWID + col*GAP,
BOTPART + row*(CHECKBOXHEIGHT + GAP),
BOTPART + (row+1)*CHECKBOXHEIGHT + row*GAP,
"NONE");
AddRadioButton(radioGroup, radioBtn);
SetVar(okBtn, DATA, radioGroup); /* ref by OKDialog */
}
return;
}
static ObjPtr OKDialog(btn)
ObjPtr btn;
{
FuncTyp OKRtn;
ObjPtr list, dialog;
int val;
list = GetVar(GetVar(btn, REPOBJ), FILELIST); /* btn's REPOBJ is dialog */
val = GetInt(GetVar(GetVar(btn, DATA), VALUE));
OKRtn = GetMethod(btn, OKMETHOD);
DeferClose();
OKRtn(val, list);
return ObjTrue;
}
static ObjPtr CancelDialog(btn)
ObjPtr btn;
{
DeferClose();
return ObjFalse;
}
/******************************************************************* GET FILE WINDOW */
#ifdef PROTO
void GetFileWindow(char *dirName)
#else
void GetFileWindow(dirName)
char *dirName;
#endif
/* Create/pop Files dialog */
{
WinInfoPtr fileWin;
ObjPtr panel, contents, corral, thePath;
ObjPtr btn, btnGroup;
int btnWid;
/* get the dialog window */
thePath = NewString(dirName);
fileWin = GetDialog((WinInfoPtr) NULLOBJ, thePath, dirName,
FILESWIDTH, FILESHEIGHT, SCRWIDTH, SCRHEIGHT, WINUI);
if(!fileWin) return;
if (GetVar((ObjPtr) fileWin, PATH)) /* dialog exists */
{
/* pop files dialog */
PopWindow(fileWin);
}
else /* create file window */
{
InhibitLogging(true);
SetVar((ObjPtr) fileWin, PATH, thePath); /* ref by this routine */
contents = GetVar((ObjPtr) fileWin, CONTENTS); /* contents of window */
/* put in help string */
SetVar((ObjPtr) fileWin, HELPSTRING, NewString("This window shows the files \
and sub-directories located in the directory given by the window's title. The files appear as \
icons corresponding to file type; sub-directories appear as folders. To open a file or \
folder, select its icon and press the Open button, or simply double click on it."));
/* put in panel */
panel = NewPanel(greyPanelClass, 0, FILESWIDTH, 0, FILESHEIGHT);
PrefixList(contents, panel);
SetVar(panel, PARENT, (ObjPtr) fileWin);
SetVar(panel, STICKINESS, NewInt(STICKYALL));
contents = GetVar(panel, CONTENTS); /* contents of panel */
/* put in icon corral */
corral = NewIconCorral(NULLOBJ, MINORBORDER,
FILESWIDTH - MINORBORDER, TITLEBOXTOP + MINORBORDER + OKBTNHT,
FILESHEIGHT - (TITLEBOXTOP + MINORBORDER + PARENTBTNHT),
OBJECTSFROMTOP + BARRIGHT + BARBOTTOM);
SetVar(corral, STICKINESS, NewInt(STICKYALL));
PrefixList(contents, corral);
SetVar(corral, PARENT, panel);
SetVar(corral, PATH, thePath);
SetVar(corral, SELECTOR, NewInt(DEFAULTFILTER)); /* file selector bits */
SetMethod(corral, SHOWFILES, ShowFiles);
SetMethod(corral, DROPINCONTENTS, DropInFileWin);
/* put in title box for filter buttons */
btn = NewTitleBox(MINORBORDER, MINORBORDER + FILTERBTNWID + 2*SMALLGAP,
FILESHEIGHT - TITLEBOXTOP - PARENTBTNHT, FILESHEIGHT - 4, "Files");
PrefixList(contents, btn);
SetVar(btn, PARENT, panel);
SetVar(btn, STICKINESS, NewInt(STICKYTOP + STICKYLEFT));
/* put in file filter radio group */
btnGroup = NewRadioButtonGroup("File Filter");
SetVar(btnGroup, PARENT, panel);
PrefixList(contents, btnGroup);
SetVar(btnGroup, CORRAL, corral);
SetVar(btnGroup, STICKINESS, NewInt(STICKYTOP + STICKYLEFT));
SetVar(btnGroup, HELPSTRING, NewString("These buttons determine which file types \
to show in the File Window. (Folders are always shown.) If the top button is checked, only SciAn \
data, log, and palette files are shown; the files must have proper filename \
extensions to be recognized by SciAn. If the bottom button is checked, all files are shown."));
btn = NewRadioButton(MINORBORDER + SMALLGAP,
MINORBORDER + SMALLGAP + FILTERBTNWID,
FILESHEIGHT - TITLEBOXTOP - PARENTBTNHT + SMALLGAP + CHECKBOXHEIGHT + CHECKBOXSPACING,
FILESHEIGHT - TITLEBOXTOP - PARENTBTNHT + SMALLGAP + 2*CHECKBOXHEIGHT + CHECKBOXSPACING,
"Show SciAn files only");
AddRadioButton(btnGroup, btn);
SetVar(btn, STICKINESS, NewInt(STICKYTOP + STICKYLEFT));
SetVar(btn, SELECTOR, NewInt(DEFAULTFILTER));
btn = NewRadioButton(MINORBORDER + SMALLGAP,
MINORBORDER + SMALLGAP + FILTERBTNWID,
FILESHEIGHT - TITLEBOXTOP - PARENTBTNHT + SMALLGAP,
FILESHEIGHT - TITLEBOXTOP - PARENTBTNHT + SMALLGAP + CHECKBOXHEIGHT,
"Show all files");
AddRadioButton(btnGroup, btn);
SetVar(btn, STICKINESS, NewInt(STICKYTOP + STICKYLEFT));
SetVar(btn, SELECTOR, NewInt(ALLFILES));
SetValue(btnGroup, NewInt(0)); /* make "Show SciAn files only" the default */
SetMethod(btnGroup, CHANGEDVALUE, NewFilter);
/* put in parent button */
btn = NewIconLabeledButton(FILESWIDTH - MINORBORDER - PARENTBTNWID,
FILESWIDTH - MINORBORDER, FILESHEIGHT - TITLEBOXTOP - PARENTBTNHT,
FILESHEIGHT - TITLEBOXTOP, ICONPARENT, UIWHITE, "Open Parent", BS_PLAIN);
SetVar(btn, STICKINESS, NewInt(STICKYTOP + STICKYRIGHT));
SetVar(btn, PARENT, panel);
SetVar(btn, LABEL, NewString("Open Parent"));
SetVar(btn, HELPSTRING, NewString("Pressing this button will \
open a new file window at the next higher directory level. The directory of the current window \
will appear as a folder in the new window."));
PrefixList(contents, btn);
MakeButtonToggled(btn, true); /* make parent button icon be lit up always */
SetValue(btn, NewInt(true));
MakeButtonToggled(btn, false);
SetVar(btn, PATH, thePath); /* ref by OpenParent */
SetMethod(btn, CHANGEDVALUE, DoParent);
SetMethod(btn, OPEN, OpenParent);
/* put in action buttons */
btnWid = (FILESWIDTH - 2*MINORBORDER - 2*SMALLGAP)/3;
btn = NewFunctionButton(fileWin, MINORBORDER, MINORBORDER + btnWid,
MINORBORDER, MINORBORDER + OKBTNHT, OF_OPEN);
if (btn)
{
SetVar(btn, PARENT, panel);
PrefixList(contents, btn);
SetVar(btn, STICKINESS, NewInt(STICKYLEFT + FLOATINGRIGHT));
}
btn = NewFunctionButton(fileWin, MINORBORDER + btnWid + SMALLGAP,
MINORBORDER + SMALLGAP + 2*btnWid,
MINORBORDER, MINORBORDER + OKBTNHT,
OF_SETFORMAT);
if (btn)
{
SetVar(btn, PARENT, panel);
PrefixList(contents, btn);
SetVar(btn, STICKINESS, NewInt(FLOATINGRIGHT + FLOATINGLEFT));
}
btn = NewFunctionButton(fileWin, FILESWIDTH - MINORBORDER - btnWid, FILESWIDTH - MINORBORDER,
MINORBORDER, MINORBORDER + OKBTNHT,
OF_SHOWINFO);
if (btn)
{
SetVar(btn, PARENT, panel);
PrefixList(contents, btn);
SetVar(btn, STICKINESS, NewInt(FLOATINGLEFT + STICKYRIGHT));
}
/* set up reference */
SetVar((ObjPtr) fileWin, CORRAL, corral); /* ref by this routine */
/* now put in the file icons */
ReadDirectory(corral);
ShowFiles(corral);
InhibitLogging(false);
}
}
#ifdef PROTO
ObjPtr IconHelp(ObjPtr icon, ObjPtr class)
#else
ObjPtr IconHelp(icon, class)
ObjPtr icon, class;
#endif
{
int type = GetInt(GetVar(icon, FILETYPE));
switch (type)
{
case DIRFILE:
SetVar(class, HELPSTRING, NewString("This icon represents a sub-directory \
within the directory of this file window. Double clicking on the folder will open a file window \
for the sub-directory."));
break;
#ifndef RELEASE
case PALFILE:
SetVar(class, HELPSTRING, NewString("This icon represents a palette file \
which has been saved by SciAn. For more information, ask Eric."));
break;
#endif
case DATAFILE:
SetVar(class, HELPSTRING, NewString("\
This icon represents a data file with a format recognized by this version of SciAn. The \
name of the format is shown under the file name. \
Double clicking on this icon will read the file into the Datasets window."));
break;
case OTHFILE:
SetVar(class, HELPSTRING, NewString("This icon represents a file whose type \
SciAn could not determine from the filename extension. If the file is a data file, you must \
identify the data format before SciAn can read the file. Select the file, press the Set \
Format button, and then select the proper format."));
break;
default:
SetVar(class, HELPSTRING, NewString("This icon represents a file in the \
directory of this file window."));
break;
}
return NULLOBJ;
}
/************************************************************************ READ DIRECTORY
* Reads directory of 'path' associated with given corral.
* Creates file objects and sets parameters for them.
*/
#ifdef PROTO
static Bool ReadDirectory(ObjPtr corral)
#else
static Bool ReadDirectory(corral)
ObjPtr corral;
#endif
{
struct stat stbuf;
int fd;
#ifdef DIRENT
struct dirent *dp;
#else
struct direct *dp;
#endif
DIR *dirp;
ObjPtr thePath, theFile;
ObjPtr fileLists, sortedLists;
int i, fileType;
ObjPtr theRdr;
char *path, *ext;
/* this may take a while */
LongOperation();
thePath = GetVar(corral, PATH);
if (thePath) path = GetString(thePath);
else return false;
if (chdir(path) != 0)
{
ReportError("ReadDirectory", "Error changing directory");
return false;
}
/* open directory */
if (!(dirp = opendir(path)))
{
ReportError("ReadDirectory", "Error opening directory");
chdir(dirSave);
return false;
}
/* set up master list and file type lists */
fileLists = NewList();
for (i=0; i<NFILETYPES; ++i) PrefixList(fileLists, NewList());
/* read directory */
while ((dp = readdir(dirp)) != NULL) /***/
{
if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) continue;
stat(dp->d_name, &stbuf);
if((stbuf.st_mode & S_IFMT) == S_IFLNK) continue; /*** must be a dead link? */
if ((stbuf.st_mode & S_IFMT) == S_IFSOCK) continue; /* socket file */
if (*dp->d_name == '.') continue; /* ignore dot files */
ext = strrchr(dp->d_name, '.'); /* point to filename extension */
/* make a file object */
theFile = NewObject(fileClass, 0);
SetVar(theFile, NAME, NewString(dp->d_name));
SetVar(theFile, PATH, thePath);
/* figure out file type */
if((stbuf.st_mode & S_IFMT) == S_IFDIR)
{
/* entry is a directory */
SetVar(theFile, FILETYPE, NewInt(DIRFILE));
PrefixList(GetListElem(fileLists, DIRFILE), theFile);
}
else
{
/* check file extension to identify file type */
if (ext++) /* skip dot */
{
if (strcmp(ext, "o") == 0)
{
/* object file */
SetVar(theFile, FILETYPE, NewInt(OBJFILE));
PrefixList(GetListElem(fileLists, OBJFILE), theFile);
}
else if (strcmp(ext, "txt") == 0
|| strcmp(ext, "c") == 0
|| strcmp(ext, "h") == 0
|| strcmp(ext, "f") == 0 )
{
/* text file */
SetVar(theFile, FILETYPE, NewInt(TEXTFILE));
PrefixList(GetListElem(fileLists, TEXTFILE), theFile);
}
else if ( theRdr = FindExtensionReader(ext) )
{
/* known data file extension */
SetVar(theFile, FILETYPE, NewInt(DATAFILE));
SetVar(theFile, READER, theRdr);
PrefixList(GetListElem(fileLists, DATAFILE), theFile);
}
else if (strcmp(ext, "log") == 0) /*** what should the ext be? */
{
/* script or log file */
SetVar(theFile, FILETYPE, NewInt(LOGFILE));
PrefixList(GetListElem(fileLists, LOGFILE), theFile);
}
#ifndef RELEASE
else if (strcmp(ext, "pal") == 0)
{
/* scian palette file */
SetVar(theFile, FILETYPE, NewInt(PALFILE));
PrefixList(GetListElem(fileLists, PALFILE), theFile);
}
#endif
else /* other file type */
{
SetVar(theFile, FILETYPE, NewInt(OTHFILE));
PrefixList(GetListElem(fileLists, OTHFILE), theFile);
}
}
else if (stbuf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
{
/* entry is (probably) executable file */
SetVar(theFile, FILETYPE, NewInt(BINFILE));
PrefixList(GetListElem(fileLists, BINFILE), theFile);
}
else /* no dot, not executable: other file type */
{
SetVar(theFile, FILETYPE, NewInt(OTHFILE));
PrefixList(GetListElem(fileLists, OTHFILE), theFile);
}
}
}
closedir(dirp);
/* now sort the lists */
sortedLists = NewList();
for (i=0; i<NFILETYPES; ++i)
PostfixList(sortedLists, SortListByStringVar(GetListElem(fileLists, i), NAME, false));
SetVar(corral, FILELIST, sortedLists);
chdir(dirSave); /* return to original directory */
return true;
}
/*********************************************************************** SHOW FILES
* Puts the icons for the selected file types into the given corral.
*/
static ObjPtr ShowFiles(corral)
ObjPtr corral;
{
ObjPtr theFile, theIcon, theRdr, iconList;
ObjPtr fileLists, theType, thePath;
ObjPtr contents;
int i, fileSelector, left, right, bottom, top, width;
ThingListPtr p;
FuncTyp ReScroll;
/* this may take a while */
LongOperation();
fileSelector = GetInt(GetVar(corral, SELECTOR));
fileLists = GetVar(corral, FILELIST);
thePath = GetVar(corral, PATH);
Get2DIntBounds(corral, &left, &right, &bottom, &top);
width = right - left;
SetVar(corral, CONTENTS, contents = NewList());
/* now drop the selected filetype icons in the corral */
for (i=0; i<NFILETYPES; ++i)
{
if (!(fileSelector & MASK(i))) continue;
theType = NewInt(i);
p = LISTOF(GetListElem(fileLists, i));
while(p)
{
theFile = p -> thing;
if (!(theIcon = GetVar(theFile, REPICON)))
{
/* make icon for this file */
theIcon = NewIcon(0, 0, fileIcon[i], GetString(GetVar(theFile, NAME)));
SetVar(theFile, REPICON, theIcon);
SetVar(theIcon, REPOBJ, theFile);
SetVar(theIcon, PARENT, corral);
SetVar(theIcon, FILETYPE, theType);
SetVar(theIcon, PATH, thePath);
SetMethod(theIcon, MAKE1HELPSTRING, IconHelp);
if (i == DIRFILE)
{
SetMethod(theFile, OPEN, OpenFolder);
}
else
{
SetMethod(theFile, OPEN, OpenFile);
SetMethod(theFile, COLLECT, Collect);
}
if (theRdr = GetVar(theFile, READER)) /* put format name on icon */
SetVar(theIcon, FORMAT, GetVar(theRdr, NAME));
}
SetVar(theIcon, ICONLOC, NULLOBJ);
PrefixList(contents, theIcon);
p = p -> next;
}
}
ScrollHome(corral);
RecalcScroll(corral);
ImInvalid(corral); /* redraw if necessary */
return ObjTrue; /* function is used as method */
}
static ObjPtr DropInFileWin(corral, icon, x, y)
ObjPtr corral, icon;
int x,y;
{
#if 0
ObjPtr theFile, theFormat, theReader;
int fileType;
theFile = GetVar(icon, REPOBJ);
if (theFile && IsFile(theFile)
{
fileType = GetInt(GetVar(theFile, FILETYPE));
if (fileType == DIRFILE)
{
DoUniqueTask(ReportCantDoIt);
return ObjFalse;
}
/* ok: to copy file need to make new icon and file objects, copy vars,
and update fileList, corral contents */
}
#else
printf("Drop in file window not implemented.\n");
#endif
return ObjFalse;
}
static ObjPtr DoParent(button)
ObjPtr button;
{
DeferMessage(button, OPEN);
return ObjTrue;
}
/* this is called only as a result of a deferred OPEN message to button */
static ObjPtr OpenParent(button)
ObjPtr button;
{
char *s, dirName[MAXPATHLEN+1];;
strncpy(dirName, GetString(GetVar(button, PATH)), MAXPATHLEN);
dirName[MAXPATHLEN] = '\0'; /* ensure termination */
s = strrchr(dirName, '/');
if (s)
{
if (s > dirName)
{
*s = '\0';
}
else
{
*(s + 1) = '\0';
}
GetFileWindow(dirName);
}
return ObjTrue;
}
/*********************************************************************** NEW FILTER */
static ObjPtr NewFilter(b)
ObjPtr b;
{
ObjPtr corral;
int selector;
corral = GetObjectVar("NewFilter", b, CORRAL);
selector = GetInt(GetVar(b, VALUE)) ? ALLFILES : DEFAULTFILTER;
SetVar(corral, SELECTOR, NewInt(selector));
ShowFiles(corral);
return ObjTrue;
}
/**************************************************************** OPEN FILE */
static ObjPtr OpenFile(theFile)
ObjPtr theFile;
/* opens (reads) one data file; returns ObjTrue if success or ObjFalse if failure */
{
ObjPtr path, reader;
reader = GetVar(theFile, READER);
path = GetStringVar("OpenFile",theFile, PATH);
if (!reader || !path || chdir(GetString(path)) != 0)
{
/***/ printf("error getting %s/%s\n",path,GetString(GetVar(theFile, NAME)));
return ObjFalse;
}
LongOperation();
ReadFormattedFile(reader, GetString(GetVar(theFile, NAME)));
/* deselect after reading */
/*** SelectIcon(GetVar(theFile, REPICON), false); ***/
/*** take out when ObjFunction changed to call RestoreDir() ***/
chdir(dirSave); /* change back to original working directory */
return ObjTrue;
}
/* This routine is called only as a result of a deferred OPEN message */
static ObjPtr OpenFolder(theFile)
ObjPtr theFile;
{
char *path, *name, dirName[MAXPATHLEN+1];
DIR *dirp;
path = GetString(GetVar(theFile, PATH));
name = GetString(GetVar(theFile, NAME));
if (strlen(path) + 1 + strlen(name) > MAXPATHLEN)
{
/* Oh, no! The dang pathname is too long! */
ReportError("OpenFolder","Oh, no! The dang pathname is too long!");
return ObjFalse;
}
strcpy(dirName, path);
if (dirName[strlen(dirName) - 1] != '/')
{
strcat(dirName, "/");
}
strcat(dirName, name);
dirName[MAXPATHLEN] = '\0';
if(dirp = opendir(dirName)) /* good path? */
{
closedir(dirp);
GetFileWindow(dirName);
return ObjTrue;
}
else
{
/* Hey! There shouldn't be an error here! */
ReportError("OpenFolder","Could not open the dang folder!");
return ObjFalse;
}
}